package com.oneline.web.components {
	import com.google.maps.styles.GradientStyle;
	import com.oneline.web.util.Logger;
	
	import flash.display.DisplayObject;
	import flash.display.GradientType;
	import flash.display.Shape;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	
	import mx.core.UIComponent;
	
	public class WFConnector extends UIComponent {
		
		private var line:Shape = new Shape;
		private var triangle:Shape = new Shape;
		private var fromBox:DisplayObject;
		private var toBox:DisplayObject;
		private var fromX:Number;
		private var toX:Number;
		private var fromY:Number;
		private var toY:Number;
		private const ARROW_SPACE:uint = 8;
		
		private var _color:uint;
		private var _thickness:uint;
		private var _directional:Boolean = true;
		private var _bending:uint = 0;
		private var _fromid:String = null;
		private var _toid:String = null;
		
		private var toDummy:WFShape = null;
		private var fromDummy:WFShape = null;
		
		public var onClick:Function;
		
		public function WFConnector() {
			fromDummy = new WFShape();
			fromDummy.width=5;
			fromDummy.height=5;
			fromDummy.label = "";
			fromDummy.color = 0x37AE99;
			fromDummy.type = 1;
			
			toDummy = new WFShape();
			toDummy.label="";
			toDummy.width=5;
			toDummy.height=5;
			toDummy.x = fromDummy.x + 80;
			toDummy.y = fromDummy.y - 30;
			toDummy.color = 0x37AE99;
			toDummy.type = 1;
			
			connect(fromDummy,toDummy,0x990000,4,true, 4);
			this.addChild(toDummy);
			this.addChild(fromDummy);
			
			this.addEventListener(Event.RESIZE, redraw);
			//			this.addEventListener(MouseEvent.CLICK, this.handleClick);
		}
		
		private function handleClick(event:MouseEvent):void
		{
			if (this.onClick != null) this.onClick(event);
		}
		
		public function get ccolor():String {
			return this._color.toString();
		}
		
		public function set ccolor(c:String):void {
			this._color = uint(c);
			drawConnector();
			drawTriangle();
		} 
		
		private var _cPoints:String = "";
		public function set cPoints(points:String):void
		{
			_cPoints = points;
		}
		
		public function get cthickness():String {
			return this._thickness.toString();
		}
		
		public function set cthickness(c:String):void {
			this._thickness = uint(c);
			drawConnector();
			drawTriangle();
		}        
		
		public function get cdirectional():String {
			if (this._directional) return "true";
			else return "false";
		}
		
		public function set cdirectional(c:String):void {
			this._directional = (c == "true");
			drawConnector();
			drawTriangle();	
		}        
		
		public function get cbending():String {
			return this._bending.toString();
		}
		
		public function set cbending(c:String):void {
			this._bending = uint(c);
			drawConnector();
			drawTriangle();			
		}        
		
		public function get cfromid():String {
			if ( null == this._fromid ) return null;
			return this._fromid.toString();
		}
		
		public function set cfromid(c:String):void 
		{
			this._fromid = c;
		}        
		
		public function get ctoid():String {
			if ( null == this._toid ) return null;
			return this._toid.toString();
		}
		
		public function set ctoid(c:String):void {
			this._toid = c;
		}
		
		private function redraw(event:Event):void 
		{
			this.fromDummy.x = this.x;
			this.toDummy.x = this.x + this.width;
			
			this.fromDummy.y = this.y;
			this.toDummy.y = this.y + this.height;
		}
		
		
		public function displace(isFrom:Boolean, x:int, y:int):void {
			if ( isFrom ) {
				this.fromBox.x = x;
				this.fromBox.y = y;
			} else {
				this.toBox.x = x;
				this.toBox.y = y;
			}
		}
		
		public function getFromBox():DisplayObject 
		{
			return this.fromBox;
		}
		
		public function getToBox():DisplayObject 
		{
			return this.toBox;
		}
		
		public function setFromBox(newFromBox:DisplayObject):void {
			if ( null == newFromBox && fromBox == fromDummy ) return;
			
			//Remove the event listing
			if ( null != fromBox ) {
				fromBox.removeEventListener(Event.ENTER_FRAME, checkForMove);
			}
			
			//If it's dummy, remove the child
			if ( fromBox == fromDummy ) {
				this.removeChild(fromBox);
			}
			
			//Unhooked the old one, add the new one
			var pos:Point = null;
			if ( null == newFromBox ) {
				if ( null != fromBox )  {
					pos = new Point( fromBox.x + (fromBox.width)/2,
						fromBox.y + (fromBox.height)/2);
				}
				fromBox = fromDummy;
				this.addChild(fromDummy);
			} else {
				fromBox = newFromBox;	
			}
			
			fromBox.addEventListener(Event.ENTER_FRAME, checkForMove);
			if ( null != pos ) {
				fromBox.x =  pos.x;
				fromBox.y =  pos.y;
			}
		}
		
		public function setToBox(newToBox:DisplayObject):void {
			if ( null == newToBox && toBox == toDummy ) return;
			
			//Remove the event listing
			if ( null != toBox ) {
				toBox.removeEventListener(Event.ENTER_FRAME, checkForMove);
			}
			
			//If it's dummy, remove the child
			if ( toBox == toDummy ) {
				this.removeChild(toBox);
			}
			
			//Unhooked the old one, add the new one
			var pos:Point = null;
			if ( null == newToBox ) {
				if ( null != toBox )  {
					pos = new Point( toBox.x + (toBox.width)/2,
						toBox.y + (toBox.height)/2);
				}
				toBox = toDummy;
				this.addChild(toDummy);
			} else {
				toBox = newToBox;
			}
			
			toBox.addEventListener(Event.ENTER_FRAME, checkForMove);
			if ( null != pos ) {
				toBox.x =  pos.x;
				toBox.y =  pos.y;
			}
		}
		
		
		public function connect(fromBox:DisplayObject, 
								toBox:DisplayObject, connectorColor:uint, 
								connectorThickness:uint, isDirectional:Boolean,bendStyle:uint):void {
			
			setFromBox(fromBox);
			setToBox(toBox);
			this._color = connectorColor
			this._thickness = connectorThickness;
			this._directional = isDirectional;
			this._bending = bendStyle;
			init();
		}
		
		private function init():void {
			fromX = fromBox.x;
			fromY = fromBox.y;
			toX = toBox.x;
			toY = toBox.y;
			_color = 0x000000;
			_thickness = 1;
			_directional = true;
			addChild(line);
			addChild(triangle);
			drawConnector();
			drawTriangle();
			
			//constantly checking to see if either display objects have moved
			fromBox.addEventListener(Event.ENTER_FRAME, checkForMove);
			toBox.addEventListener(Event.ENTER_FRAME, checkForMove);
		}
		
		private function checkForMove(event:Event):void {
			if((fromX!=fromBox.x)||(fromY!=fromBox.y)||(toX!=toBox.x)||(toY!=toBox.y)){
				drawConnector();
				fromX = fromBox.x;
				fromY = fromBox.y;
				toX = toBox.x;
				toY = toBox.y;
			}
		}
		
		private function drawConnector():void {
			line.graphics.clear();
			line.graphics.lineStyle(_thickness, _color, 1);
			//			line.graphics.lineGradientStyle(GradientType.RADIAL, [0xFFFF00, 0xFF0000], [1,1], [50, 50]);
			if ( 0 == _bending ) drawContainerAuto();
			else if ( 1 == _bending ) bottomToTop();
			else if ( 2 == _bending ) topToBottom();
			else if ( 3 == _bending ) leftToRight();
			else if ( 4 == _bending ) rightToLeft();
			else if ( 5 == _bending ) centerToCenter();
			else if ( 6 == _bending ) leftToTop();
			else if ( 7 == _bending ) topToLeft();
			else if ( 8 == _bending ) rightToTop();
			else if ( 9 == _bending ) topToRight();
			else if ( 10 == _bending ) rightToBottom();
			else if ( 11 == _bending ) bottomToRight();
			else if ( 12 == _bending ) leftToBottom();
			else if ( 13 == _bending ) bottomToLeft();
			else if ( 14 == _bending ) leftToLeft();
			else if ( 15 == _bending ) rightToRight();
			else if ( 16 == _bending ) topToTop();
			else if ( 17 == _bending ) bottomToBottom();
			else drawContainerAuto();
		}
		
		public static function getBendAsName(bendI : int):String {
			var bendN:String = "";
			switch (bendI) {
				case 0 	: bendN = "AA"; break;
				case 1 	: bendN = "BT"; break;
				case 2 	: bendN = "TB"; break;
				case 3 	: bendN = "LR"; break;
				case 4 	: bendN = "RL"; break;
				case 5 	: bendN = "CC"; break;
				case 6 	: bendN = "LT"; break;
				case 7 	: bendN = "TL"; break;
				case 8 	: bendN = "RT"; break;
				case 9 	: bendN = "TR"; break;
				case 10 : bendN = "RB"; break;
				case 11 : bendN = "BR"; break;
				case 12	: bendN = "LB"; break;
				case 13 : bendN = "BL"; break;
				case 14 : bendN = "LL"; break;
				case 15 : bendN = "RR"; break;
				case 16 : bendN = "TT"; break;
				case 17 : bendN = "BB"; break;
				default : bendN = "AA";  break;
			} 
			return bendN;
		}
		
		public static function getBendType(typeName:String):int
		{
			var bendType:int = 0;
			switch(typeName)
			{
				case "BT" : bendType = 1 ; break;
				case "TB" : bendType = 2 ; break;
				case "LR" : bendType = 3 ; break;
				case "RL" : bendType = 4 ; break;
				case "CC" : bendType = 5; break;
				case "LT" : bendType = 6; break;
				case "TL" : bendType = 7; break;
				case "RT" : bendType = 8; break;
				case "TR" : bendType = 9; break;
				case "RB" : bendType = 10; break;
				case "BR" : bendType = 11; break;
				case "LB" : bendType = 12; break;
				case "BL" : bendType = 13; break;
				case "LL" : bendType = 14; break;
				case "RR" : bendType = 15; break;
				case "TT" : bendType = 16; break;
				case "BB" : bendType = 17; break;
				default : bendType = 0; break;
			}
			return bendType;
		}
		
		private function drawContainerAuto():void {
			if(isFullyLeftOf(fromBox, toBox)){
				if(isFullyAbove(fromBox, toBox)){
					bottomToTop();
				}
				else if(isFullyBelow(fromBox, toBox)){
					topToBottom();
				}
				else{
					rightToLeft();
				}
			}
			else if(isFullyRightOf(fromBox, toBox)){
				if(isFullyAbove(fromBox, toBox)){
					bottomToTop();
				}
				else if(isFullyBelow(fromBox, toBox)){
					topToBottom();
				}
				else{
					leftToRight();
				}            
			}
			else if(isFullyAbove(fromBox, toBox)){
				bottomToTop();
			}
			else if(isFullyBelow(fromBox, toBox)){
				topToBottom();
			}
			else{
				centerToCenter();
			}        	
		}
		
		//this is the arrow on the end of the line
		private function drawTriangle():void {
			triangle.graphics.clear();
			triangle.graphics.beginFill(lineColor, 1);
			triangle.graphics.moveTo(lineThickness+1.5, 0);
			triangle.graphics.lineTo(-(lineThickness+1.5), 0);
			triangle.graphics.lineTo(0, ARROW_SPACE);
			triangle.graphics.lineTo(lineThickness+1.5, 0);
			triangle.graphics.endFill();
		}
		
		public function reverse():void {
			var temp:DisplayObject = fromBox;
			fromBox = toBox;
			toBox = temp;
		}
		
		public function set lineThickness(value:uint):void {
			_thickness = value;
			drawTriangle();
			drawConnector();
		}
		
		public function get lineThickness():uint {
			return _thickness;
		}
		
		public function set lineColor(value:uint):void {
			_color = value;
			drawTriangle();
			drawConnector();
			
		}
		
		public function get lineColor():uint {
			return _color;
		}
		
		public function getParent():DisplayObject {
			return fromBox;
		}
		
		public function setParent(value:DisplayObject):void {
			fromBox = value;
			drawTriangle();
			drawConnector();
		}
		
		public function getChild():DisplayObject {
			return toBox;
		}
		
		public function setChild(value:DisplayObject):void {
			toBox = value;
			drawTriangle();
			drawConnector();
		}
		
		public function set usePointer(value:Boolean):void {
			_directional = value;
			drawTriangle();
			drawConnector();
			
		}
		
		public function get usePointer():Boolean {
			return _directional;
		}

		//from the right side of obj1 to the left side of obj2
		private function rightToLeft():void {
			leftToRightImpl (this.toBox, this.fromBox, false);			
		}
		
		//from the left side of obj1 to the right side of obj2
		private function leftToRight():void {
			leftToRightImpl (this.fromBox, this.toBox, true);			
		}
		
		private function leftToRightImpl(fromO:DisplayObject, toO:DisplayObject, arrow:Boolean ):void {
	
			var endX:int = toO.x + toO.width;
			var endY:int = toO.y + toO.height / 2;
			var startY:int = fromO.y + fromO.height / 2;
			var midX:int = fromO.x + (endX - fromO.x)/2;
			line.graphics.moveTo(fromO.x , startY);
			if ( fromO.x > endX ) {
				line.graphics.lineTo(midX, startY );
				line.graphics.lineTo(midX, endY);
				line.graphics.lineTo(endX, endY);
			} else {
				line.graphics.lineTo(fromO.x - 12 , startY );
				var gt:int = 0;
				if (fromO.y > toO.y ) gt = fromO.y - 12;
				else if (fromO.y + fromO.height > toO.y ) gt = fromO.y - 12;
				else gt = fromO.y + fromO.height + 12;
				line.graphics.lineTo(fromO.x - 12 , gt );
				line.graphics.lineTo(endX + 12 , gt);
				line.graphics.lineTo(endX + 12 , endY );
				line.graphics.lineTo(endX, endY);
			}
			if(_directional) {
				triangle.visible = true;
				triangle.y = toBox.y + toBox.height/2;
				if ( arrow ) {
					triangle.x = (toBox.x + toBox.width) + ARROW_SPACE;
					triangle.rotation = 90;
				} else {
					triangle.x = toBox.x - ARROW_SPACE;
					triangle.rotation = -90;
				}
			} else {
				triangle.visible = false;
			}
		}		
	
	
		//from the top of obj1 to the bottom of obj2
		private function topToBottom():void {
			bottomToTopImpl(this.toBox,this.fromBox, false);
		}
		
		private function bottomToTop():void {
			bottomToTopImpl(this.fromBox, this.toBox, true);
		}
		
		private function bottomToTopImpl(fromO:DisplayObject, toO:DisplayObject, arrow:Boolean ):void {
			var fromBotX:int = fromO.x + (fromO.width/2);
			var fromBotY:int = fromO.y + fromO.height;
			var endX:int = toO.x + (toO.width/2);
			var midY:int = fromBotY + (toO.y - fromBotY)/2;
			line.graphics.moveTo(fromBotX, fromBotY);
			if ( fromBotY <= toO.y ) {
				line.graphics.lineTo(fromBotX, midY );
				line.graphics.lineTo(endX, midY);
				line.graphics.lineTo(endX, toO.y);
			} else {
				line.graphics.lineTo(fromBotX, fromBotY  + 12);
				var nearX:int = ((toO.width + 12) / 2);
				nearX =	( endX >=fromBotX) ? nearX * 1 : nearX * -1; 
				line.graphics.lineTo(endX - nearX, fromBotY  + 12);
				line.graphics.lineTo(endX - nearX, toO.y - 12);
				line.graphics.lineTo(endX , toO.y - 12);
				line.graphics.lineTo(endX, toO.y);
			}
			if(_directional) {
				triangle.visible = true;
				triangle.x = (toBox.x + (toBox.width/2));
				if ( arrow ) {
					triangle.y = toBox.y - ARROW_SPACE;
					triangle.rotation = 0;
					
				} else {
					triangle.y = (toBox.y + toBox.height)+ ARROW_SPACE;
					triangle.rotation = 180;
					
				}
			} else {
				triangle.visible = false;
			}
		}		
		
		
		//from the bottom of obj1 to the top of obj2
		private function leftToTop():void {
			this.leftToTopImpl(this.fromBox, this.toBox, true);
		}
		
		private function topToLeft():void {
			this.leftToTopImpl(this.toBox, this.fromBox, false);
		}
		
		private function leftToTopImpl(fromO:DisplayObject, toO:DisplayObject, arrow:Boolean ):void {
			var endX:int = toO.x + (toO.width/2);
			var startY:int = fromO.y + fromO.height / 2;
			var midX:int = fromO.x - 12;
			
			line.graphics.moveTo(fromO.x , startY);
			if ( fromO.x > endX ) {
				line.graphics.lineTo(midX, startY );
				line.graphics.lineTo(midX, toO.y - 12);
				line.graphics.lineTo(endX, toO.y - 12);
				line.graphics.lineTo(endX, toO.y);
			} else {
				line.graphics.lineTo(fromO.x - 12, startY );
				var gt:int = 0;
				if (fromO.y > toO.y ) gt = toO.y - 12;
				else if (fromO.y + fromO.height > toO.y ) gt = toO.y - 12;
				else gt = toO.y - 12;
				line.graphics.lineTo(fromO.x - 12 , gt );
				line.graphics.lineTo(endX, gt);
				line.graphics.lineTo(endX, toO.y - 12);
				line.graphics.lineTo(endX, toO.y);
			}
			if(_directional) {
				triangle.visible = true;
				if ( arrow ) {
					triangle.x = (toBox.x + (toBox.width/2));
					triangle.y = toBox.y - ARROW_SPACE;
					triangle.rotation = 0;
				} else {
					triangle.x = toBox.x - ARROW_SPACE;
					triangle.y = toBox.y + toBox.height/2;
					triangle.rotation = -90;
				}
			} else {
				triangle.visible = false;
			}
			
		}
		
		//from the bottom of obj1 to the top of obj2
		private function rightToTop():void {
			this.rightToTopImpl(this.fromBox, this.toBox, true);
		}
		
		private function topToRight():void {
			this.rightToTopImpl(this.toBox, this.fromBox, false);
		}
		
		private function rightToTopImpl(fromO:DisplayObject, toO:DisplayObject, arrow:Boolean ):void {
			var startX:int = fromO.x + (fromO.width);
			var endX:int = toO.x + (toO.width/2);
			var startY:int = fromO.y + fromO.height / 2;
			var midX:int = startX + 12;
			
			line.graphics.moveTo(startX, startY);
			if ( startX > endX ) {
				line.graphics.lineTo(midX, startY );
				line.graphics.lineTo(midX, toO.y - 12);
				line.graphics.lineTo(endX, toO.y - 12);
				line.graphics.lineTo(endX, toO.y);
			} else {
				midX = startX + (toO.x - startX ) / 2;
				if ( midX < 0 ) midX = startX + 6;
				line.graphics.lineTo(midX, startY );
				var gt:int = 0;
				if (fromO.y > toO.y ) gt = toO.y - 12;
				else if (fromO.y + fromO.height > toO.y ) gt = toO.y - 12;
				else gt = toO.y - 12;
				line.graphics.lineTo(midX , gt );
				line.graphics.lineTo(endX, gt);
				line.graphics.lineTo(endX, toO.y - 12);
				line.graphics.lineTo(endX, toO.y);
			}
			if(_directional) {
				triangle.visible = true;
				if ( arrow ) {
					triangle.x = (toBox.x + (toBox.width/2));
					triangle.y = toBox.y - ARROW_SPACE;
					triangle.rotation = 0;
				} else {
					triangle.x = toBox.x + toBox.width + ARROW_SPACE;
					triangle.y = toBox.y + toBox.height/2;
					triangle.rotation = 90;
				}
			} else {
				triangle.visible = false;
			}
		}
		
		private function rightToBottom():void {
			this.rightToBottomImpl(this.fromBox, this.toBox, true);
		}
		
		private function bottomToRight():void {
			this.rightToBottomImpl(this.toBox, this.fromBox, false);
		}
		
		private function rightToBottomImpl(fromO:DisplayObject, toO:DisplayObject, arrow:Boolean ):void {
			var offsetFX:int = fromO.width;
			var offsetTX:int = toO.width/2;
			
			var offsetFY:int = fromO.height / 2;
			var offsetTY:int = toO.height;
			
			var startX:int = fromO.x + offsetFX;
			var endX:int = toO.x + offsetTX;
			var startY:int = fromO.y + offsetFY;
			var endY:int = toO.y + offsetTY;
			var gap:int = (offsetFX > 0 ) ? + 12 : - 12;
			var midX:int  = startX + gap;
			
			line.graphics.moveTo(startX, startY);
			if ( startX > endX ) {
				line.graphics.lineTo(midX, startY );
				line.graphics.lineTo(midX, endY + gap);
				line.graphics.lineTo(endX, endY + gap);
				line.graphics.lineTo(endX, endY);
			} else {
				if ( startY < endY) {
					line.graphics.lineTo(startX+12, startY);
					line.graphics.lineTo(startX+12, endY+12);
					line.graphics.lineTo(endX, endY+12);
					line.graphics.lineTo(endX, endY);
				} else {
					line.graphics.lineTo(endX, startY);
					line.graphics.lineTo(endX, endY);
				}
			}
			if(_directional) {
				triangle.visible = true;
				if ( arrow ) {
					triangle.x = endX;
					triangle.y = endY + ARROW_SPACE;
					triangle.rotation = 180;
				} else {
					triangle.x = startX + ARROW_SPACE;
					triangle.y = startY;
					triangle.rotation = 90;
				}
			} else {
				triangle.visible = false;
			}
		}

		
		private function leftToBottom():void {
			this.leftToBottomImpl(this.fromBox, this.toBox, true);
		}
		
		private function bottomToLeft():void {
			this.leftToBottomImpl(this.toBox, this.fromBox, false);
		}
		
		private function leftToBottomImpl(fromO:DisplayObject, toO:DisplayObject, arrow:Boolean ):void {
			var startX:int = fromO.x;
			var endX:int = toO.x + (toO.width/2);
			var startY:int = fromO.y + fromO.height / 2;
			var endY:int = toO.y + toO.height;
			var midX:int = startX - 12;
			
			line.graphics.moveTo(startX, startY);
			if ( startX > endX ) {
				line.graphics.lineTo(midX, startY );
				line.graphics.lineTo(midX, endY + 12);
				line.graphics.lineTo(endX, endY + 12);
				line.graphics.lineTo(endX, endY);
			} else {
				midX = startX + (endX - startX ) / 2;
				if ( midX > fromO.x ) midX = startX - 12;
				line.graphics.lineTo(midX, startY );
				
				var gt:int = 0;
				if (fromO.y > toO.y ) gt = endY + 12;
				else if (fromO.y + fromO.height > toO.y ) gt = endY + 12;
				else gt = endY + 12;
				
				line.graphics.lineTo(midX , gt );
				line.graphics.lineTo(endX, gt );
				line.graphics.lineTo(endX, endY);
			}
			if(_directional) {
				triangle.visible = true;
				if ( arrow ) {
					triangle.x = endX;
					triangle.y = endY + ARROW_SPACE;
					triangle.rotation = 180;
				} else {
					triangle.x = toBox.x - ARROW_SPACE;
					triangle.y = toBox.y + toBox.height/2;
					triangle.rotation = -90;
				}
			} else {
				triangle.visible = false;
			}
		}
		
		private function leftToLeft():void {
			
			var startX:int = fromBox.x;
			var endX:int = toBox.x ;
			var startY:int = fromBox.y + fromBox.height / 2;
			var endY:int = toBox.y + toBox.height / 2;
			
			var midX:int = startX - 12;
			line.graphics.moveTo(startX, startY);
			if ( startX < endX ) {
				line.graphics.lineTo(midX, startY );
				line.graphics.lineTo(midX, endY);
				line.graphics.lineTo(endX, endY);
			} else {
				if ( ! (toBox.y < startY && startY < (toBox.y + toBox.height)) ){
					midX = toBox.x - 12;
				}
				line.graphics.lineTo(midX, startY );
				
				var gt:int = 0;
				if (fromBox.y > toBox.y ) gt = toBox.y + toBox.height;
				else gt = toBox.y  - 12;
				
				line.graphics.lineTo(midX , gt );
				line.graphics.lineTo(endX-12, gt );
				line.graphics.lineTo(endX-12, endY );
				line.graphics.lineTo(endX, endY);
			}
			if(_directional) {
				triangle.visible = true;
				triangle.x = endX - ARROW_SPACE;
				triangle.y = endY ;
				triangle.rotation = -90;
			} else {
				triangle.visible = false;
			}
		}
		
		private function rightToRight():void {
			var startX:int = fromBox.x + fromBox.width;
			var endX:int = toBox.x + toBox.width;
			var startY:int = fromBox.y + fromBox.height / 2;
			var endY:int = toBox.y + toBox.height / 2;
			
			var nextX:int = this.toBox.x;
			line.graphics.moveTo(startX, startY);
			if ( startX < endX ) {
				nextX = endX + 12;
				line.graphics.lineTo(nextX, startY );
				line.graphics.lineTo(nextX, endY);
				line.graphics.lineTo(endX, endY);
				
			} else {
				line.graphics.lineTo(startX+12, startY );
				if ( endY > fromBox.y &&  endY < (fromBox.y + fromBox.height) ) {
					line.graphics.lineTo(startX+12, this.fromBox.y - 12);   
					line.graphics.lineTo(this.fromBox.x - 12, this.fromBox.y - 12);   
					line.graphics.lineTo(this.fromBox.x - 12, endY);      
				} else {
					line.graphics.lineTo(startX+12, endY);    
				}
				line.graphics.lineTo(endX, endY);
			}
			if(_directional) {
				triangle.visible = true;
				triangle.x = endX + ARROW_SPACE;
				triangle.y = endY ;
				triangle.rotation = 90;
			} else {
				triangle.visible = false;
			}
		}
		
		private function topToTop():void {
			var startX:int = fromBox.x + fromBox.width/2;
			var endX:int = toBox.x + toBox.width/2;
			var startY:int = fromBox.y ;
			var endY:int = toBox.y ;
			
			var nextY:int = this.toBox.y;
			line.graphics.moveTo(startX, startY);
			if ( startY > endY ) {
				nextY = endY - 12;
			} else {
				nextY = startY - 12;
			}
			
			if ( startX > toBox.x &&  startX < (toBox.x + toBox.width) ) {
				line.graphics.lineTo(startX, startY - 12);
				line.graphics.lineTo(fromBox.x - 12, startY - 12);
				line.graphics.lineTo(fromBox.x - 12, endY - 12);
				line.graphics.lineTo(endX, endY - 12);
			} else {
				line.graphics.lineTo(startX, nextY );
				line.graphics.lineTo(endX, nextY);
			}
			line.graphics.lineTo(endX, endY);
			
			
			if(_directional) {
				triangle.visible = true;
				triangle.x = endX ;
				triangle.y = endY - ARROW_SPACE;
				triangle.rotation = 0;
			} else {
				triangle.visible = false;
			} 
		}
		
		private function bottomToBottom():void {
			var startX:int = fromBox.x + fromBox.width/2;
			var endX:int = toBox.x + toBox.width/2;
			var startY:int = fromBox.y + fromBox.height;
			var endY:int = toBox.y + toBox.height;
			
			var nextY:int = this.toBox.y;
			line.graphics.moveTo(startX, startY);
			if ( endY > startY ) {
				nextY = endY + 12;
			} else {
				nextY = startY + 12;
			}
			
			if ( startX > toBox.x &&  startX < (toBox.x + toBox.width) ) {
				line.graphics.lineTo(startX, startY + 12);
				line.graphics.lineTo(fromBox.x - 12, startY + 12);
				line.graphics.lineTo(fromBox.x - 12, endY + 12);
				line.graphics.lineTo(endX, endY + 12);
			} else {
				line.graphics.lineTo(startX, nextY );
				line.graphics.lineTo(endX, nextY);
			}
			line.graphics.lineTo(endX, endY);
			
			
			if(_directional) {
				triangle.visible = true;
				triangle.x = endX ;
				triangle.y = endY + ARROW_SPACE;
				triangle.rotation = 180;
			} else {
				triangle.visible = false;
			} 
		}


		
		//from the center of _obj1 to the center of _obj2
		private function centerToCenter():void {
			line.graphics.moveTo(fromBox.x + (fromBox.width/2), fromBox.y + (fromBox.height/2));
			line.graphics.lineTo(toBox.x + (toBox.width/2), toBox.y + (toBox.height/2));
			triangle.visible = false;
		}
		
		//checks if obj1 is fully above obj2 (this includes the space for the arrow)
		private function isFullyAbove(obj1:DisplayObject, obj2:DisplayObject):Boolean {
			return (obj1.y + obj1.height + ARROW_SPACE) < obj2.y;
		}
		
		//checks if obj1 is fully below obj2 (this includes the space for the arrow)
		private function isFullyBelow(obj1:DisplayObject, obj2:DisplayObject):Boolean {
			return obj1.y > (obj2.y + obj2.height + ARROW_SPACE);
		}
		
		//checks if obj1 is fully to the left of obj2 (this includes the space for the arrow)
		private function isFullyLeftOf(obj1:DisplayObject, obj2:DisplayObject):Boolean {
			return (obj1.x + obj1.width + ARROW_SPACE) < obj2.x;
		}
		
		//checks if obj1 is fully to the right of obj2 (this includes the space for the arrow)
		private function isFullyRightOf(obj1:DisplayObject, obj2:DisplayObject):Boolean {
			return obj1.x > (obj2.x + obj2.width + ARROW_SPACE);
		}        
		
	}
}

